package com.tgh.utils;



public class GLFrame {
    
    protected Vector3f vOrigin;
    protected Vector3f vForward;
    protected Vector3f vUp;

    public GLFrame(){
        vOrigin=new Vector3f(0, 0, 0);
        vUp=new Vector3f(0, 1, 0);
        vForward=new Vector3f(0, 0, -1);
    }
    
    public Vector3f getOrigin() {
        return vOrigin.clone();
    }
    
    public void getOrigin(Vector3f vector) {
        vector.copy(vOrigin);
    }
    
    public float getOriginX() {
        return vOrigin.x;
    }
    
    public float getOriginY() {
        return vOrigin.y;
    }
    
    public float getOriginZ() {
        return vOrigin.z;
    }
    
    public void setOrigin(Vector3f vOrigin) {
        this.vOrigin.copy(vOrigin);
    }
    
    public void setOrigin(float x,float y,float z) {
        this.vOrigin.copy(x,y,z);
    }

    public Vector3f getForwardVector() {
        return vForward.clone();
    }
    
    public void getForwardVector(Vector3f vect) {
        vect.copy(vForward);
    }
    
    public void setForwardVector(Vector3f vForward) {
        this.vForward.copy(vForward);
    }
    
    public void setForwardVector(float x,float y,float z) {
        this.vForward.copy(x,y,z);
    }

    public Vector3f getUpVector() {
        return vUp.clone();
    }
    
    public void getUpVector(Vector3f vect) {
        vect.copy(vUp);
    }
    
    public void setUpVector(Vector3f vUp) {
        this.vUp.copy(vUp);
    }
    
    public void setUpVector(float x,float y,float z) {
        this.vUp.copy(x,y,z);
    }
    
    public Vector3f getZAxis() {
        return vForward;
    }
    
    public Vector3f getYAxis() {
        return vUp;
    }
    
    public Vector3f getXAxis() {
        return Vector3f.crossProduct(vUp, vForward);
    }
    
    public void translateWorld(float x, float y, float z) {
        vOrigin.x+=x;
        vOrigin.y+=y;
        vOrigin.z+=z;
    }
    
    public void translateLocal(float x, float y, float z) {
        moveForward(z);
        moveUp(y);
        moveRight(x);
    }
    
    /**
     * 沿着z轴
     * @param fDelta
     */
    public void moveForward(float fDelta) {
        vOrigin.x+=vForward.x*fDelta;
        vOrigin.y+=vForward.y*fDelta;
        vOrigin.z+=vForward.z*fDelta;
    }
    /**
     * 沿着Y轴
     * @param fDelta
     */
    public void moveUp(float fDelta) {
        vOrigin.x+=vUp.x*fDelta;
        vOrigin.y+=vUp.y*fDelta;
        vOrigin.z+=vUp.z*fDelta;
    }
    /**
     * 沿着x轴
     * @param fDelta
     */
    public void moveRight(float fDelta) {
        Vector3f xAxis = getXAxis();
        vOrigin.x+=xAxis.x*fDelta;
        vOrigin.y+=xAxis.y*fDelta;
        vOrigin.z+=xAxis.z*fDelta;
    }
    
    public void getMatrix(Matrix44f matrix) {
        matrix.loadIdentity();
        Vector3f xAxis = getXAxis();
        matrix.setMatrixColumn44(xAxis, 0);
        matrix.setMatrixColumn44(vUp, 1);
        matrix.setMatrixColumn44(vForward, 2);
        matrix.setMatrixColumn44(vOrigin, 3);
    }
    
    public void getRotationMatrix(Matrix33f matrix) {
        matrix.loadIdentity();
        Vector3f xAxis = getXAxis();
        matrix.setMatrixColumn(xAxis, 0);
        matrix.setMatrixColumn(vUp, 1);
        matrix.setMatrixColumn(vForward, 2);
    }
    
    public void getRotationMatrix(Matrix44f matrix) {
        matrix.loadIdentity();
        Vector3f xAxis = getXAxis();
        matrix.setMatrixColumn44(xAxis, 0);
        matrix.setMatrixColumn44(vUp, 1);
        matrix.setMatrixColumn44(vForward, 2);
    }
    
    public Matrix44f getMatrix() {
        Matrix44f matrix=new Matrix44f();
        getMatrix(matrix);
        return matrix;
    }
    
    public void getCameraMatrix(Matrix44f m,boolean rotationOnly) {
        Vector3f z=new Vector3f(-vForward.x,-vForward.y,-vForward.z);
        Vector3f xAxis = Vector3f.crossProduct(vUp, z);
        m.loadIdentity();
        Matrix33f matrix33=new Matrix33f();
        matrix33.setMatrixColumn(xAxis, 0);
        matrix33.setMatrixColumn(vUp, 1);
        matrix33.setMatrixColumn(z, 2);
        matrix33.transpose();
        m.replaceWithRotationMatrix(matrix33);
        if (!rotationOnly) {
            m.translate(-vOrigin.x, -vOrigin.y, -vOrigin.z);
        }
    }
    
    public Matrix44f getCameraMatrix(boolean rotationOnly) {
        Matrix44f matrix=new Matrix44f();
        getCameraMatrix(matrix,rotationOnly);
        return matrix;
    }
    
    public void rotateLocalY(float fAngle) {
        Matrix44f rotMat=new Matrix44f();
        rotMat.loadRotate(fAngle, vUp.x, vUp.y, vUp.z);
        Vector3f newVect=new Vector3f();
        Math3D.rotateVector3(newVect, vForward, rotMat);
        vForward.copy(newVect);
    }
    
    public void rotateLocalZ(float fAngle) {
        Matrix44f rotMat=new Matrix44f();
        rotMat.loadRotate(fAngle, vForward.x, vForward.y, vForward.z);
        Vector3f newVect=new Vector3f();
        Math3D.rotateVector3(newVect, vUp, rotMat);
        vUp.copy(newVect);
    }
    
    public void rotateLocalX(float fAngle) {
        Matrix33f rotMat=new Matrix33f();
        Vector3f xAxis = getXAxis();
        rotMat.loadRotate(fAngle, xAxis.x, xAxis.y, xAxis.z);
        
        Vector3f rotVec =new Vector3f();
        Math3D.rotateVector3(rotVec, vUp, rotMat);
        vUp.copy(rotVec);
        Math3D.rotateVector3(rotVec, vForward, rotMat);
        vForward.copy(rotVec);
    }
    
    
    public void normalize() {
        Vector3f vCross;
        vCross=Vector3f.crossProduct(vUp, vForward);
        vForward.copy(Vector3f.crossProduct(vCross, vUp));
        vUp.normalize();
        vForward.normalize();
    }

    public void rotateWorld(float fAngle, float x, float y, float z){
        Matrix44f rotMat=new Matrix44f();
        rotMat.loadRotate(fAngle, x, y, z);
        Vector3f result=new Vector3f();
        Math3D.rotateVector3(result, vUp, rotMat);
        vUp.copy(result);
        Math3D.rotateVector3(result, vForward, rotMat);
        vForward.copy(result);
    }
       

    public void rotateLocal(float fAngle, float x, float y, float z){
        Vector3f vWorldVect=new Vector3f();
        Vector3f vLocalVect=new Vector3f(x,y,z);
        localToWorld(vLocalVect, vWorldVect, true);
        rotateWorld(fAngle, vWorldVect.x, vWorldVect.y, vWorldVect.z);
    }
    
    
    public void localToWorld(Vector3f vLocal,Vector3f vWorld,boolean rotOnly) {
        Matrix33f rotMat=new Matrix33f();
        getRotationMatrix(rotMat);
        Math3D.rotateVector3(vWorld, vLocal, rotMat);
        // Translate the point
        if(!rotOnly) {
            vWorld.x+=vOrigin.x;
            vWorld.y+=vOrigin.y;
            vWorld.z+=vOrigin.z;
        }
    }
    
    public void worldToLocal(Vector3f vWorld, Vector3f vLocal){
        Vector3f newWorld=new Vector3f();
        newWorld.x=vWorld.x-vOrigin.x;
        newWorld.y=vWorld.y-vOrigin.y;
        newWorld.z=vWorld.z-vOrigin.z;
        
        Matrix33f rotMat=new Matrix33f();
        getRotationMatrix(rotMat);
        rotMat.transpose();
        Math3D.rotateVector3(vLocal, newWorld, rotMat);
    }

    public void transformPoint(Vector3f vPointSrc, Vector3f vPointDst) {
        Matrix44f mat=new Matrix44f();
        getMatrix(mat);
        Math3D.transformVector3(vPointDst, vPointSrc, mat);
    }
         
   public void rotateVector(Vector3f vPointSrc, Vector3f vPointDst) {
       Matrix33f rotMat=new Matrix33f();
       getRotationMatrix(rotMat);
       Math3D.rotateVector3(vPointDst, vPointSrc, rotMat);
   }    
}
